@@ -4,13 +4,61 @@ |
||
4 | 4 |
# or operating system, you probably want to add a global ignore instead: |
5 | 5 |
# git config --global core.excludesfile '~/.gitignore_global' |
6 | 6 |
|
7 |
-# Ignore bundler config. |
|
7 |
+*.rbc |
|
8 |
+capybara-*.html |
|
9 |
+.rspec |
|
10 |
+/log |
|
11 |
+/tmp |
|
12 |
+/db/*.sqlite3 |
|
13 |
+/public/system |
|
14 |
+/coverage/ |
|
15 |
+/spec/tmp |
|
16 |
+**.orig |
|
17 |
+rerun.txt |
|
18 |
+pickle-email-*.html |
|
19 |
+ |
|
20 |
+config/initializers/secret_token.rb |
|
21 |
+config/secrets.yml |
|
22 |
+ |
|
23 |
+## Environment normalisation: |
|
8 | 24 |
/.bundle |
25 |
+/vendor/bundle |
|
9 | 26 |
|
10 |
-# Ignore the default SQLite database. |
|
11 |
-/db/*.sqlite3 |
|
12 |
-/db/*.sqlite3-journal |
|
27 |
+# these should all be checked in to normalise the environment: |
|
28 |
+# Gemfile.lock, .ruby-version, .ruby-gemset |
|
13 | 29 |
|
14 |
-# Ignore all logfiles and tempfiles. |
|
15 |
-/log/*.log |
|
16 |
-/tmp |
|
30 |
+# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: |
|
31 |
+.rvmrc |
|
32 |
+ |
|
33 |
+# if using bower-rails ignore default bower_components path bower.json files |
|
34 |
+/vendor/assets/bower_components |
|
35 |
+*.bowerrc |
|
36 |
+bower.json |
|
37 |
+ |
|
38 |
+.DS_Store |
|
39 |
+.AppleDouble |
|
40 |
+.LSOverride |
|
41 |
+ |
|
42 |
+# Icon must end with two \r |
|
43 |
+Icon |
|
44 |
+ |
|
45 |
+# Thumbnails |
|
46 |
+._* |
|
47 |
+ |
|
48 |
+# Files that might appear on external disk |
|
49 |
+.Spotlight-V100 |
|
50 |
+.Trashes |
|
51 |
+ |
|
52 |
+# Directories potentially created on remote AFP share |
|
53 |
+.AppleDB |
|
54 |
+.AppleDesktop |
|
55 |
+Network Trash Folder |
|
56 |
+Temporary Items |
|
57 |
+.apdisk |
|
58 |
+ |
|
59 |
+# Ignore application configuration |
|
60 |
+/config/application.yml |
|
61 |
+ |
|
62 |
+# Ignore File Uploads |
|
63 |
+/public/uploads |
|
64 |
+/public/ . |
@@ -25,6 +25,7 @@ class AgentController < ApplicationController |
||
25 | 25 |
@user = User.find(current_user.id) |
26 | 26 |
@mission_invite = @user.mission_agent_invites.find(params[:id]) |
27 | 27 |
@mission_invite.status = 'denied' |
28 |
+ @mission_invite.mission_agent.assign_agent |
|
28 | 29 |
respond_to do |format| |
29 | 30 |
if @mission_invite.save |
30 | 31 |
format.html { redirect_to missions_path, notice: 'Mission was denied.' } |
@@ -76,33 +76,10 @@ class MissionsController < ApplicationController |
||
76 | 76 |
@mission.status = 'Launched' |
77 | 77 |
respond_to do |format| |
78 | 78 |
if @mission.save |
79 |
- @users = User.all |
|
80 |
- @mission_agents = @mission.mission_agents.all |
|
81 |
- @users.each do |user| |
|
82 |
- @invited = false |
|
83 |
- @mission_agents.each do |agent| |
|
84 |
- if agent.user != user |
|
85 |
- agent.mission_agent_invites.each do |invite| |
|
86 |
- if invite.user == user |
|
87 |
- # user already invited |
|
88 |
- @invited = true |
|
89 |
- end |
|
90 |
- end |
|
91 |
- else |
|
92 |
- @invited = true |
|
93 |
- end |
|
94 |
- end |
|
95 |
- if @invited == false |
|
96 |
- @mission_agents.each do |agent| |
|
97 |
- if agent.user == nil |
|
98 |
- agent.user_id = user.id |
|
99 |
- agent.mission_agent_invites.create!(:user_id => user.id, :status => 'invited') |
|
100 |
- agent.save |
|
101 |
- end |
|
102 |
- end |
|
103 |
- end |
|
79 |
+ @mission.mission_agents.each do |agent| |
|
80 |
+ agent.assign_agent |
|
104 | 81 |
end |
105 |
- format.html { redirect_to @mission, notice: 'Mission launched!' } |
|
82 |
+ format.html { redirect_to mission_control_path(@mission), notice: 'Mission launched!' } |
|
106 | 83 |
format.json { head :no_content } |
107 | 84 |
else |
108 | 85 |
format.html { render action: 'edit' } |
@@ -148,6 +125,7 @@ class MissionsController < ApplicationController |
||
148 | 125 |
@step.mission_agent.mission_agent_invites.where(:user => @step.mission_agent.user).last.update(:status => "Completed") |
149 | 126 |
end |
150 | 127 |
@mission = @step.mission_agent.mission |
128 |
+ @mission.validade_completion |
|
151 | 129 |
redirect_to mission_control_path(@mission), notice: 'Step Validated!' |
152 | 130 |
end |
153 | 131 |
|
@@ -3,4 +3,33 @@ class Mission < ActiveRecord::Base |
||
3 | 3 |
has_many :mission_agents, :dependent => :destroy |
4 | 4 |
has_many :mission_agent_steps, :through => :mission_agents |
5 | 5 |
accepts_nested_attributes_for :mission_agents, allow_destroy:true |
6 |
+ |
|
7 |
+ def validade_completion |
|
8 |
+ mission_completed = true |
|
9 |
+ self.mission_agents.each do |agent| |
|
10 |
+ if agent.get_invite.status != 'Completed' |
|
11 |
+ mission_completed = false |
|
12 |
+ end |
|
13 |
+ end |
|
14 |
+ if mission_completed |
|
15 |
+ self.status = "Completed" |
|
16 |
+ self.save |
|
17 |
+ end |
|
18 |
+ end |
|
19 |
+ |
|
20 |
+ def has_agent_been_assigned(user) |
|
21 |
+ self.mission_agents.each do |agent| |
|
22 |
+ if agent.user != user |
|
23 |
+ agent.mission_agent_invites.each do |invite| |
|
24 |
+ if invite.user == user |
|
25 |
+ return true |
|
26 |
+ end |
|
27 |
+ end |
|
28 |
+ else |
|
29 |
+ return true |
|
30 |
+ end |
|
31 |
+ end |
|
32 |
+ return false |
|
33 |
+ end |
|
34 |
+ |
|
6 | 35 |
end |
@@ -7,4 +7,22 @@ class MissionAgent < ActiveRecord::Base |
||
7 | 7 |
|
8 | 8 |
accepts_nested_attributes_for :mission_agent_steps, allow_destroy:true |
9 | 9 |
accepts_nested_attributes_for :mission_agent_invites |
10 |
+ |
|
11 |
+ def get_invite |
|
12 |
+ return self.mission_agent_invites.where(:user => self.user).last |
|
13 |
+ end |
|
14 |
+ |
|
15 |
+ def assign_agent |
|
16 |
+ users = User.all |
|
17 |
+ available_agents = Array.new |
|
18 |
+ users.each do |u| |
|
19 |
+ if self.mission.has_agent_been_assigned(u) == false |
|
20 |
+ available_agents << u |
|
21 |
+ end |
|
22 |
+ end |
|
23 |
+ new_agent = available_agents[rand(available_agents.length)] |
|
24 |
+ self.update(:user => new_agent) |
|
25 |
+ self.mission_agent_invites.create!(:user => new_agent, :status => 'Invited') |
|
26 |
+ end |
|
27 |
+ |
|
10 | 28 |
end |
@@ -4,6 +4,9 @@ |
||
4 | 4 |
<% if mission.status == 'Launched' %> |
5 | 5 |
<% @status_label = 'label-success'%> |
6 | 6 |
<% end%> |
7 |
+<% if mission.status == 'Completed' %> |
|
8 |
+ <% @status_label = 'label-success'%> |
|
9 |
+<% end%> |
|
7 | 10 |
|
8 | 11 |
<% if big == true %> |
9 | 12 |
<span class="label <%= @status_label %> pull-right" style="margin-top: 2px; padding-left: 20px; padding-right: 20px"> |
@@ -0,0 +1,282 @@ |
||
1 |
+# Avalanche |
|
2 |
+ |
|
3 |
+Avanche is an online plataform where you play the role of an agent and gets assigned to real life missions. |
|
4 |
+ |
|
5 |
+1. Spread the Knoleage |
|
6 |
+2. Disobey |
|
7 |
+3. Resist |
|
8 |
+ |
|
9 |
+## Pages |
|
10 |
+ |
|
11 |
+- Home Page |
|
12 |
+ - System Statistics (Completed Missions | On Going Missions | Number of Agents) |
|
13 |
+ - Call To Arms (login) |
|
14 |
+ - Game description |
|
15 |
+- About |
|
16 |
+ - Introduction |
|
17 |
+ - Game Rules |
|
18 |
+ - Dev Team |
|
19 |
+- Login |
|
20 |
+- Signup |
|
21 |
+- Missions |
|
22 |
+ - Current Missions |
|
23 |
+ - Mission Select |
|
24 |
+ - Mission Control List |
|
25 |
+ - Create new Mission button |
|
26 |
+- Mission Details |
|
27 |
+ - Mission Details |
|
28 |
+ - Mission Steps |
|
29 |
+ - Step Validation |
|
30 |
+- Create/Edit Mission |
|
31 |
+- Mission Control |
|
32 |
+- Agent Profile |
|
33 |
+ - Agent Stats |
|
34 |
+ - Mission History |
|
35 |
+- Edit Agent Profile |
|
36 |
+ |
|
37 |
+## System |
|
38 |
+ |
|
39 |
+- Background Jobs |
|
40 |
+- Hash URLs |
|
41 |
+- No Turbolinks! |
|
42 |
+- Mission Acomplished Email |
|
43 |
+ |
|
44 |
+## Tables |
|
45 |
+ |
|
46 |
+#### Users |
|
47 |
+ |
|
48 |
+- username |
|
49 |
|
|
50 |
+- password |
|
51 |
+- location |
|
52 |
+- Limites |
|
53 |
+ |
|
54 |
+#### Missions |
|
55 |
+ |
|
56 |
+- title |
|
57 |
+- description |
|
58 |
+- agent_search_start_date |
|
59 |
+- agent_search_end_date |
|
60 |
+- Status (Initializing -> Launched -> Active -> (Complete, Falied, Canceled or Closed) |
|
61 |
+ |
|
62 |
+#### Mission Agent |
|
63 |
+ |
|
64 |
+- mission_id |
|
65 |
+- description (if no steps) |
|
66 |
+- location |
|
67 |
+- reward |
|
68 |
+- user_id : int |
|
69 |
+- agent_name : string |
|
70 |
+- anonymous_agent : bool |
|
71 |
+ |
|
72 |
+#### Mission Agent Step |
|
73 |
+ |
|
74 |
+- mission_agent_id |
|
75 |
+- step_number |
|
76 |
+- description |
|
77 |
+- completed : bool |
|
78 |
+- proof_type |
|
79 |
+- proof |
|
80 |
+- validated : bool |
|
81 |
+- validated_by :user |
|
82 |
+- status (In Progress, Incomplete, Waiting Validation, Completed, Failed, Canceled, Locked) |
|
83 |
+ |
|
84 |
+#### Mission Agent Invite |
|
85 |
+ |
|
86 |
+- user |
|
87 |
+- status (Waiting, Accepted, Denied, Expired) |
|
88 |
+ |
|
89 |
+ |
|
90 |
+## Rails Development Steps |
|
91 |
+ |
|
92 |
+``` bash |
|
93 |
+ |
|
94 |
+# Step 1 |
|
95 |
+rails new avalanche_game --database=postgresql |
|
96 |
+ |
|
97 |
+# Step 2 - Create databases |
|
98 |
+ |
|
99 |
+# Step 3 - Install Gems |
|
100 |
+ |
|
101 |
+# Step 4 - Inialize plugins (bootstrap, flatstrap, simpl_form, friendly_id) |
|
102 |
+rails generate bootstrap:install |
|
103 |
+rails generate bootstrap:layout application fluid |
|
104 |
+rails generate bootstrap:layout front_end fixed |
|
105 |
+rails generate bootstrap:layout auth fixed |
|
106 |
+rails generate simple_form:install --bootstrap |
|
107 |
+rails generate friendly_id |
|
108 |
+ |
|
109 |
+# Step 5 - Initialize Devise |
|
110 |
+rails generate devise:install |
|
111 |
+rails generate devise user username:string location:string |
|
112 |
+rails g devise:views |
|
113 |
+rake db:migrate |
|
114 |
+ |
|
115 |
+# Step 6 - Scaffold |
|
116 |
+rails g scaffold mission title:string description:text status:string agent_search_start:datetime agent_search_end:datetime |
|
117 |
+rails g model mission_agent mission:references description:text location:string reward:text user:references agent_name:string anonymous_agent:bool |
|
118 |
+rails g model mission_agent_step mission_agent:references step:integer description:text completed:bool proof_type:string proof:string |
|
119 |
+rails g controller agent current_missions choose_mission agent_profile |
|
120 |
+rails g controller start index about |
|
121 |
+ |
|
122 |
+# Step 7 - Modify |
|
123 |
+rails g model mission_agent_invite user:reference mission_agent:references status:string |
|
124 |
+rails g migration AddInviteToMissionAgent mission_agent_invites:references |
|
125 |
+rails g migration AddOwnerToMission owner:references |
|
126 |
+rails g migration AddValidationToMissionAgentStep validated:boolean validated_by:references |
|
127 |
+ |
|
128 |
+``` |
|
129 |
+ |
|
130 |
+## Badges/Trophies/Perks |
|
131 |
+ |
|
132 |
+- Recruiter |
|
133 |
+- Missao Acomplished |
|
134 |
+- Fast Responder |
|
135 |
+- Field Agent |
|
136 |
+- Mission Planner |
|
137 |
+- Beta Tester |
|
138 |
+- Years of service |
|
139 |
+ |
|
140 |
+## Videos |
|
141 |
+ |
|
142 |
+* [TED - The case for collaborative consumption](http://www.ted.com/talks/rachel_botsman_the_case_for_collaborative_consumption#) |
|
143 |
+ |
|
144 |
+## Layout References |
|
145 |
+ |
|
146 |
+* [Agency Layout](http://startbootstrap.com/templates/agency/) |
|
147 |
+* [FlatStrap](http://flatstrap.org/) |
|
148 |
+* [Timeline 1](http://bootsnipp.com/snippets/featured/timeline-21-with-images-and-responsive), [Timeline 2](http://bootsnipp.com/snippets/featured/timeline-dotted), [Timeline 3](http://bootsnipp.com/snippets/featured/two-column-timeline-not-responsive) |
|
149 |
+* [Comments](http://bootsnipp.com/snippets/featured/recent-comments-admin-panel) |
|
150 |
+* [Carousel](http://bootsnipp.com/snippets/featured/bootstrap-carousel-with-text) |
|
151 |
+* [Blog Post](http://bootsnipp.com/snippets/featured/complete-blog-layout) |
|
152 |
+* [Progress Bar](http://bootsnipp.com/snippets/featured/progress-bar-example) |
|
153 |
+* [User Profile](http://bootsnipp.com/snippets/featured/user-profile-widget) |
|
154 |
+* [Badges](http://bootsnipp.com/snippets/featured/hero-widgets) |
|
155 |
+* [Date Picker](http://bootsnipp.com/snippets/featured/simple-datepicker-with-momentjs) |
|
156 |
+* [Simple Invoice](http://bootsnipp.com/snippets/featured/simple-invoice) |
|
157 |
+* [Ideal Image Slider](http://gilbitron.github.io/Ideal-Image-Slider/) |
|
158 |
+ |
|
159 |
+## Plugins |
|
160 |
+ |
|
161 |
+* [Bootstrap Select](http://silviomoreto.github.io/bootstrap-select/) |
|
162 |
+* [Bootstrap Location Picker](https://github.com/abdelilah/bootstrap-locationpicker) |
|
163 |
+* [Bootstrap timepicker rails addon](https://github.com/ywjno/bootstrap-timepicker-rails-addon) |
|
164 |
+* [Bootstrap timepicker rails](https://github.com/tispratik/bootstrap-timepicker-rails) |
|
165 |
+* [bootstrap-tags](https://github.com/Serhioromano/bootstrap-tags) |
|
166 |
+* [awesome_nested_fields](https://github.com/lailsonbm/awesome_nested_fields) |
|
167 |
+* [Chartist.js](http://gionkunz.github.io/chartist-js/) - Simple responsive charts |
|
168 |
+ |
|
169 |
+## Services |
|
170 |
+ |
|
171 |
+* [Terms Feed](https://termsfeed.com) - Generate a Free Terms of Service Agreement in minutes. |
|
172 |
+ |
|
173 |
+## Tutorials |
|
174 |
+ |
|
175 |
+* [Ruby on Rails Tutorial (3rd Ed.)](http://news.railstutorial.org/rails_tutorial_3rd_edition/) |
|
176 |
+ |
|
177 |
+## Todo List |
|
178 |
+ |
|
179 |
+#### Version 0.1 |
|
180 |
+ |
|
181 |
+[X] Ajax create/delete agents |
|
182 |
+[X] User List |
|
183 |
+[X] Choose Mission Page |
|
184 |
+[X] Accept/Denie missions |
|
185 |
+[X] Agent Missions |
|
186 |
+[X] Missions List |
|
187 |
+[X] Mission Control / Mission Description |
|
188 |
+[X] Step Validation |
|
189 |
+[X] Mission Completed |
|
190 |
+[X] Mission owner |
|
191 |
+[X] Randomize algorithm |
|
192 |
+[X] User Page |
|
193 |
+[ ] Start Page - add sys statisitcs and how to play text |
|
194 |
+[X] Redirect to missions page after login and signup |
|
195 |
+[ ] Edit Profile Layout |
|
196 |
+[ ] Mission Form |
|
197 |
+[X] Agent Mission History |
|
198 |
+[ ] Access control |
|
199 |
+[X] Run Algorithm every time something changes |
|
200 |
+[ ] Sign In Redirect |
|
201 |
+[ ] Heroku Upload |
|
202 |
+[ ] Empty Dashboard |
|
203 |
+ |
|
204 |
+#### Version 0.2 |
|
205 |
+ |
|
206 |
+[ ] Background Tasks (Redis) |
|
207 |
+[ ] Translations |
|
208 |
+[ ] Invite Timer |
|
209 |
+[ ] Mission Timer |
|
210 |
+[ ] Step Timer |
|
211 |
+[ ] About Page |
|
212 |
+[ ] Email system |
|
213 |
+[ ] New mission email alert |
|
214 |
+ |
|
215 |
+## Bugs |
|
216 |
+ |
|
217 |
+- After Mission Launch, agents that were not found are shown as invited |
|
218 |
+- Mission in dashboard that the owner is an agent needs a button for "mission details" |
|
219 |
+- Steps are out of order in mission control |
|
220 |
+- Agent steps layout in mission control with more than 3 items |
|
221 |
+- Sign In redirects to home page instead of mission dashboard |
|
222 |
+- (SERIOUS) Step validation in mission control. Rails server crashes after accepting anwser |
|
223 |
+- Do not assign the owner of a mission as one of its agents |
|
224 |
+ |
|
225 |
+## Code Clipper |
|
226 |
+ |
|
227 |
+``` ruby |
|
228 |
+# Loop thru all mission_agents and each mission_agent_steps attributes and save them all |
|
229 |
+# Nasty override code for a neste models bug that was resolved in the project |
|
230 |
+@mission.assign_attributes(params[:mission_agents_attributes]) |
|
231 |
+@mission.assign_attributes(params[:mission_agent_steps_attributes]) |
|
232 |
+params[:mission][:mission_agents_attributes].values.each do |a| |
|
233 |
+ if a[:mission_agent_steps_attributes] != nil |
|
234 |
+ a[:mission_agent_steps_attributes].values.each do |s| |
|
235 |
+ @step = MissionAgentStep.where(:id => s[:id]).first_or_create |
|
236 |
+ if s[:_destroy] == 1.to_s |
|
237 |
+ @step.destroy |
|
238 |
+ else |
|
239 |
+ @step.mission_agent_id = a[:id] |
|
240 |
+ @step.description = s[:description] |
|
241 |
+ @step.save |
|
242 |
+ end |
|
243 |
+ # Update Step Order |
|
244 |
+ @steps = MissionAgentStep.order(:step => :asc).find_all_by_mission_agent_id(@step.mission_agent) |
|
245 |
+ @step_number = 1 |
|
246 |
+ @steps.each do |step| |
|
247 |
+ step.step = @step_number |
|
248 |
+ step.save |
|
249 |
+ @step_number = @step_number + 1 |
|
250 |
+ end |
|
251 |
+ end |
|
252 |
+ end |
|
253 |
+end |
|
254 |
+ |
|
255 |
+# Initial Algorithm |
|
256 |
+ @users = User.all |
|
257 |
+ @mission_agents = @mission.mission_agents.all |
|
258 |
+ @users.each do |user| |
|
259 |
+ @invited = false |
|
260 |
+ @mission_agents.each do |agent| |
|
261 |
+ if agent.user != user |
|
262 |
+ agent.mission_agent_invites.each do |invite| |
|
263 |
+ if invite.user == user |
|
264 |
+ # user already invited |
|
265 |
+ @invited = true |
|
266 |
+ end |
|
267 |
+ end |
|
268 |
+ else |
|
269 |
+ @invited = true |
|
270 |
+ end |
|
271 |
+ end |
|
272 |
+ if @invited == false |
|
273 |
+ @mission_agents.each do |agent| |
|
274 |
+ if agent.user == nil |
|
275 |
+ agent.user_id = user.id |
|
276 |
+ agent.mission_agent_invites.create!(:user_id => user.id, :status => 'invited') |
|
277 |
+ agent.save |
|
278 |
+ end |
|
279 |
+ end |
|
280 |
+ end |
|
281 |
+ end |
|
282 |
+``` |